<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <title>综合案例：简易购物车</title>
    <meta name="viewport"
        content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
    <meta name="description" content="" />
    <meta name="keywords" content="" />
    <link href="" rel="stylesheet" />
</head>

<body>
    <!-- 
        > 细节：
            >
            > - 展示基本的商品信息
            > - 计算每个商品的小计
            > - 商品数量的加、减操作
            >   - +：增加商品数量，同时更新小计
            >   - -：减少商品熟练，同时更新小计，如果本身为“1”，再点-号则需要移除商品

            > 如果需要在Vue实例中访问自身data属性中的数据，可以使用以下方式：
            >
            > - this.xxxxx
            > - this.$data.xxxxx
            > - this._data.xxxxx

        > 细节2：
            > - 给页面加上全选/全不选的复选框（单个复选框）bool值
            > - 给每个条目都加上复选框（多个复选框）array类型+value属性
            > - 根据业务实现对应的效果

        > 细节3：
            - 增加自动计算总价功能，只计算被选中的商品【计算属性】
            - 增加反选功能【事件绑定】
            - 当手动选中全部商品，`全选`复选框自动选中，但凡有一个商品的复选框没有被选中，则`全选`复选框不选中【监听器】
     -->
    <div id="app">
        <ul>
            <!-- 单个复选框，要求v-model绑定布尔值 -->
            <li>
                <input type="checkbox" v-model="isCheckAll" @change="checkAll" />全选&emsp; <button
                    @click="fanxuan">反选</button>
            </li>
            <li v-for="(item,index) in cartData" :key="item.id">
                <!-- 多个复选框，要求v-model绑定数组，并且配合value属性使用 -->
                <input type="checkbox" :value="item.id" v-model="buys" /> 商品id：{{item.id}}&emsp;
                商品名称：{{item.name}}&emsp; 商品单价：{{item.price}}&emsp; 购买数量： <button @click="reduce(item,index)">-</button>
                {{item.num}} <button @click="add(item,index)">+</button> &emsp; 商品小计：{{item.price * item.num}}
            </li>
            <!-- 汇总环节 -->
            <li>总价是：{{total.toFixed(2)}} 元</li>
        </ul>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        // 购物车的数据源
        var cartData = [
            {
                id: 1,
                name: '小米',
                price: 100,
                num: 1
            },
            {
                id: 2,
                name: '华为',
                price: 200,
                num: 1
            },
            {
                id: 3,
                name: '联想',
                price: 300,
                num: 1
            }
        ]
        new Vue({
            el: "#app",
            data: {
                // 声明vue的数据
                cartData,
                // 是否全选的bool值（默认补权限）
                isCheckAll: false,
                // 需要购买的商品（数组，默认为空）
                buys: []
            },
            methods: {
                // -1的操作方法
                reduce(item, index) {
                    if (item.num === 1) {
                        // 如果再-就变0，移除该商品
                        // if(confirm("这么好的商品，确定不要来一个吗？")){
                        //     this.cartData.splice(index, 1)
                        // }
                        // a && b，只有当a为真的时候才会走b，如果a为假，则b不走
                        confirm("这么好的商品，确定不要来一个吗？") && this.cartData.splice(index, 1)
                    } else {
                        // 数量大于1，够减，继续-1
                        item.num--
                    }
                },
                // +1的操作方法
                add(item, index) {
                    // console.log(item, index);
                    // this.cartData[index].num++
                    // 定论：在js中数组/对象其值的传递方式是引用传递
                    item.num++
                    // console.log(this);
                },
                // 全选/全不选
                checkAll() {
                    // 107行有几个意思？
                    // 两层含义：1针对全选前的清空，防止追加；2全不选的清空
                    this.buys = []
                    // 全选：单个复选框选中，后面所有的复选框跟着选中
                    if (this.isCheckAll) {
                        // 单个复选框选中，后面所有的复选框跟着选中
                        this.cartData.forEach(el => {
                            this.buys.push(el.id)
                        })
                    }
                },
                // 反选操作
                fanxuan() {
                    // 思路：
                    // 1. 理解什么是反选？   指的是，在反选完成后，原本的每个条目选中状态会被取反的操作。
                    // 2. 实现：因为需要挨个记录取反操作，所以不建议直接在操作过程中去修改buys的数据。建议搞一个临时的变量存储最终的结果，然后覆盖buys
                    let tmp = [];
                    // 不要循环buys，因为循环buys取不到其它信息的
                    this.cartData.forEach(el => {
                        // 判断一下当前循环到的商品是否在buys中
                        !this.buys.includes(el.id) && tmp.push(el.id)
                    })
                    // 将临时的数据赋值给buys即可
                    this.buys = tmp
                }
            },
            // 计算属性
            computed: {
                // 获取总价的计算属性
                total: function () {
                    // 公式：  总价 = 商品数量 * 商品单价 + 商品数量 * 商品单价 ....
                    // 定义变量：累加器
                    let sum = 0;
                    // 累加环节
                    this.cartData.forEach(el => {
                        // 判断一下当前的商品是否是被选中的商品
                        // 思路：只需要判断当前的商品是否在this.buys中即可
                        // 问题：如何判断一个元素是否存在于另一个数组中呢？
                        //      方案1：通过indexOf来寻找出现的位置，如果出现则存在
                        //      方案2：通过es6新增的数组api：includes来判断是否包含某元素
                        // if (this.buys.indexOf(el.id) > -1) {
                        if (this.buys.includes(el.id)) {
                            // 在this.buys中，需要我们累加价格
                            sum += el.num * el.price
                        }
                    })
                    // 返回处理好的累加数据
                    return sum;
                }
            },
            // 监听器
            watch: {
                // 需要先明白这个需求需要监听谁
                buys: function () {
                    // 思路：buys的数组长度=cartData长度
                    // 代码1：
                    // if (this.buys.length === this.cartData.length) {
                    //     this.isCheckAll = true;
                    // } else {
                    //     this.isCheckAll = false;
                    // }
                    // 代码2：
                    // this.buys.length === this.cartData.length ? this.isCheckAll = true : this.isCheckAll = false
                    // 代码3：
                    this.isCheckAll = this.buys.length === this.cartData.length
                }
            }
        })
    </script>
</body>

</html>